/*
 *   Copyright 2008 Francois Fernandes
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package com.googlecode.opendoclibrary.internal.impl.fs.meta;

import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.googlecode.opendoclibrary.internal.impl.fs.Assert;
import com.googlecode.opendoclibrary.library.spi.RegisteredNamespace;

final class VirtualRegisteredNamespacesMap implements Map<String, String>
{
    private Map<String, RegisteredNamespace> registeredNamespaces;

    public VirtualRegisteredNamespacesMap( Map<String, RegisteredNamespace> registeredNamespaces )
    {
        super();
        Assert.notNull( registeredNamespaces, "registeredNamespaces may not be null" );
        this.registeredNamespaces = registeredNamespaces;
    }

    @Override
    public void clear()
    {
        throwReadOnly();
    }

    @Override
    public boolean containsKey( Object key )
    {
        return registeredNamespaces.containsKey( key );
    }

    @Override
    public boolean containsValue( Object value )
    {
        return values().contains( value );
    }

    @Override
    public Set<Entry<String, String>> entrySet()
    {
        HashSet<Entry<String, String>> entries = new HashSet<Entry<String, String>>();
        for ( RegisteredNamespace rn : registeredNamespaces.values() )
        {
            entries.add( new VirtualRegisteredNamespacesEntry( rn ) );
        }
        return entries;
    }

    @Override
    public String get( Object key )
    {
        if ( key instanceof String )
        {
            RegisteredNamespace rn = registeredNamespaces.get( key );
            if ( rn != null )
            {
                return rn.getNamespaceURI().toString();
            }
        }
        return null;
    }

    @Override
    public boolean isEmpty()
    {
        return registeredNamespaces.isEmpty();
    }

    @Override
    public Set<String> keySet()
    {
        return registeredNamespaces.keySet();
    }

    @Override
    public String put( String key, String value )
    {
        throwReadOnly();
        // will not be reached
        return null;
    }

    @Override
    public void putAll( Map<? extends String, ? extends String> m )
    {
        throwReadOnly();
    }

    @Override
    public String remove( Object key )
    {
        throwReadOnly();
        // will not be reached
        return null;
    }

    @Override
    public int size()
    {
        return registeredNamespaces.size();
    }

    private void throwReadOnly()
    {
        throw new UnsupportedOperationException(
                                                 "this virtual map provides read only access to the namespace registry." );
    }

    @Override
    public Collection<String> values()
    {
        // in our case the value is the namespace URI
        try
        {
            List<String> values = new ArrayList<String>( registeredNamespaces.size() );
            for ( RegisteredNamespace rn : registeredNamespaces.values() )
            {
                values.add( rn.getNamespaceURI().toString() );
            }
            return values;
        }
        catch ( ConcurrentModificationException e )
        {
            // as it is uncommon to throw a CME for values, retry
            return values();
        }
    }

}